/*
 * #%L
 * java model
 * %%
 * Copyright (C) 2009 - 2011 prefabware.com Stefan Isele
 * %%
 * All Rights Reserved.
 * This program is dual-licensed under the GNU General Public license
 * or a commercial license.
 * You may select to use one or the other of these licenses.
 * To obtain a commercial license please contact Stefan Isele at www.stefan-isele.de
 * Any modifications to this file must keep this entire header intact.
 * Redistribution, except as permitted by the selected license, is prohibited.
 * #L%
 */
package com.prefabware.jmodel;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.prefabware.commons.CollectionUtil;
import com.prefabware.commons.QualifiedName;
import com.prefabware.jmodel.code.CodeBuffer;
import com.prefabware.jmodel.code.JCodeOptions;
import com.prefabware.jmodel.reference.JReference;

public class JClass extends JTypeWithFields {
	/**
	 * the constructors declared in this class, without those inherited from
	 * superclasses
	 */
	private List<JConstructor> constructors;
	private JClass extends_;
	private boolean abstract_;
	private List<JInterface> implements_;

	public JClass(QualifiedName qn, JTypeDeclaration declaration) {
		super(qn, declaration);
		this.implements_ = new ArrayList<JInterface>();
		this.constructors = new ArrayList<JConstructor>();
	}

	public boolean add(JConstructor constructor) {
		constructor.setDeclaringType(this);
		return constructors.add(constructor);
	}

	public boolean add(JInterface arg0) {
		return implements_.add(arg0);
	}

	public JClass getExtends() {
		return extends_;
	}

	public List<JInterface> getImplements() {
		return Collections.unmodifiableList(implements_);
	}

	public void setExtends(JClass extends1) {
		extends_ = extends1;
	}

	public List<JConstructor> getConstructors() {
		return Collections.unmodifiableList(constructors);
	}

	/**
	 * @return the default constructor is a constructor without arguments.
	 *         returns null if the class has none
	 */
	public JConstructor getDefaultConstructor() {
		for (JConstructor con : this.getConstructors()) {
			if (con.getArguments().size() == 0) {
				return con;
			}
		}
		return null;
	}

	public boolean isAbstract_() {
		return abstract_;
	}

	public void setAbstract_(boolean abstract_) {
		this.abstract_ = abstract_;
	}

	public List<JReference<?>> getReferences() {
		List<JReference<?>> references = new ArrayList<JReference<?>>();
		references.addAll(super.getReferences());
		for (JConstructor constructor : getConstructors()) {
			references.addAll(constructor.getReferences());
		}
		return references;
	}

	@Override
	public String getJavaKeyword() {
		return "class";
	}

	/**
	 * TODO rename to getField when getField was renamed to getDeclaredField
	 * 
	 * @param fieldName
	 * @return the field with the given name
	 */
	public JField getAllField(String fieldName) {
		JClass current = this;
		while (current != null) {
			JField field = current.getAllField(fieldName);
			if (field != null) {
				return field;
			} else {
				current = this.getExtends();
			}
		}

		return null;
	}

	public List<JField> getAllFields() {
		List<JField> all = new ArrayList<JField>();
		if (this.getExtends() != null) {
			all.addAll(this.getExtends().getAllFields());
		}
		//now add my fields to override inherited once
		//TODO implement override
		all.addAll(this.getFields());
		return all;
	}
	
}
